﻿using Daemon.Common;
using Daemon.Data.Infrastructure.Auth;
using Daemon.Middleware;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace Daemon.Common.Auth
{
	public class SecuredItemAuthorizeAttribute : AuthorizeAttribute
	{
		private string _securedItem = string.Empty;

		private string[] _securedItems = new string[1];

		/// <summary>
		/// securedItem property
		/// </summary>
		public string SecuredItem
		{
			get
			{
				return _securedItem;
			}

			set
			{
				_securedItem = value;
				_securedItems = value.Split('|');
			}
		}

		public override void OnAuthorization(HttpActionContext actionContext)
		{
		
		}

		private void SendUnauthrizedResponse(HttpActionContext actionContext)
		{
			actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden, new ResultModel(HttpStatusCode.Forbidden, "The roles of this user doesn't have the right to access this API"));
		}

		/// <summary>
		/// Authenticatication specified secured item.
		/// </summary>
		/// <param name="securedItemAuth"></param>
		/// <param name="securedItemName"></param>
		/// <param name="securedItemRights"></param>
		/// <param name="httpMethod"></param>
		/// <returns></returns>
		private bool AuthenticateSecuredItem(JToken securedItemAuth, string securedItemName, string[] securedItemRights, HttpMethod httpMethod)
		{
			if (securedItemAuth != null)
			{
				if (securedItemAuth.Any(c => string.Equals("Batch", c.ToString(), StringComparison.OrdinalIgnoreCase)))
				{
					return true;
				}

				// Authentication specified permission type
				if (securedItemRights != null)
				{
					foreach (var rightName in securedItemRights)
					{
						if (securedItemAuth.Any(c => string.Equals(rightName.Trim(), c.ToString(), StringComparison.OrdinalIgnoreCase)))
						{
							return true;
						}
					}
				}// If permission type not specified for the endpoint
				else if ((httpMethod == HttpMethod.Get && securedItemAuth.Any(c => string.Equals("Read", c.ToString(), StringComparison.OrdinalIgnoreCase)))
					|| ((httpMethod == HttpMethod.Put || httpMethod == HttpMethod.Post || httpMethod == new HttpMethod("PATCH")) && securedItemAuth.Any(c => "Add Save Edit".ToLower().Contains(c.ToString().ToLower())))
					|| (httpMethod == HttpMethod.Delete && securedItemAuth.Any(c => string.Equals("Delete", c.ToString(), StringComparison.OrdinalIgnoreCase))))
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// Check the secured item is null or empty.
		/// If the secured item from attribute is null or empty, gets the secured item from controller secured item name.
		/// </summary>
		/// <param name="actionContext">http action context</param>
		/// <returns>Is the secured item is null or empty</returns>
		private bool IsSecuredItemNullOrEmpty(HttpActionContext actionContext)
		{
			return false;
		}

		private bool SkipAuthorization(HttpActionContext actionContext)
		{
			Contract.Assert(actionContext != null);

			if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()
				|| actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
			{
				return true;
			}

			return false;
		}
	}
}
